From: Matthieu Gallien Date: Mon, 5 May 2025 16:40:35 +0000 (+0200) Subject: fix(rename): avoid failing hard when rename is rejected by server X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1^2~13^2~1^2~28^2 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/www.github.com/%22bookmarks:///%22http:/www.example.com/cgi/%22https:/www.github.com/%22bookmarks:/?a=commitdiff_plain;h=dfa6a63355348474934f9b909ff81cf306d60bf7;p=nextcloud-desktop.git fix(rename): avoid failing hard when rename is rejected by server Signed-off-by: Matthieu Gallien --- diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index 9b72732c4..7edd68467 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -180,11 +180,10 @@ QPair DiscoveryPhase::findAndCancelDeletedJob(const QString &o result = true; oldEtag = (*it)->_etag; } else { - if (!(instruction == CSYNC_INSTRUCTION_REMOVE - // re-creation of virtual files count as a delete - || ((*it)->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW) - || ((*it)->_isRestoration && instruction == CSYNC_INSTRUCTION_NEW))) - { + if (!(instruction == CSYNC_INSTRUCTION_REMOVE || + instruction == CSYNC_INSTRUCTION_IGNORE || + ((*it)->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW) ||// re-creation of virtual files count as a delete + ((*it)->_isRestoration && instruction == CSYNC_INSTRUCTION_NEW))) { qCWarning(lcDiscovery) << "ENFORCE(FAILING)" << originalPath; qCWarning(lcDiscovery) << "instruction == CSYNC_INSTRUCTION_REMOVE" << (instruction == CSYNC_INSTRUCTION_REMOVE); qCWarning(lcDiscovery) << "((*it)->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW)" diff --git a/test/testsyncmove.cpp b/test/testsyncmove.cpp index 246d34882..52d0051b6 100644 --- a/test/testsyncmove.cpp +++ b/test/testsyncmove.cpp @@ -1372,6 +1372,54 @@ private slots: QVERIFY(dbResult); QCOMPARE(itemsCounter, 12); } + + void testRenameFileThatExistsInMultiplePaths() + { + FakeFolder fakeFolder{FileInfo{}}; + QObject parent; + + fakeFolder.setServerOverride([&parent](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *) -> QNetworkReply * { + if (op == QNetworkAccessManager::CustomOperation + && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("MOVE")) { + return new FakeErrorReply(op, request, &parent, 507); + } + return nullptr; + }); + + fakeFolder.remoteModifier().mkdir("FolderA"); + fakeFolder.remoteModifier().mkdir("FolderA/folderParent"); + fakeFolder.remoteModifier().insert("FolderA/folderParent/FileA.txt"); + fakeFolder.remoteModifier().mkdir("FolderB"); + fakeFolder.remoteModifier().mkdir("FolderB/folderChild"); + fakeFolder.remoteModifier().insert("FolderB/folderChild/FileA.txt"); + fakeFolder.remoteModifier().mkdir("FolderC"); + + const auto fileAFileInfo = fakeFolder.remoteModifier().find("FolderB/folderChild/FileA.txt"); + const auto fileAInFolderAFolderFileId = fileAFileInfo->fileId; + const auto fileAInFolderAEtag = fileAFileInfo->etag; + const auto duplicatedFileAFileInfo = fakeFolder.remoteModifier().find("FolderB/folderChild/FileA.txt"); + + duplicatedFileAFileInfo->fileId = fileAInFolderAFolderFileId; + duplicatedFileAFileInfo->etag = fileAInFolderAEtag; + + QVERIFY(fakeFolder.syncOnce()); + + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + + fakeFolder.localModifier().rename("FolderA/folderParent/FileA.txt", "FolderC/FileA.txt"); + + qDebug() << fakeFolder.currentLocalState(); + + fakeFolder.syncEngine().setLocalDiscoveryOptions(OCC::LocalDiscoveryStyle::FilesystemOnly); + QVERIFY(!fakeFolder.syncOnce()); + + qDebug() << fakeFolder.currentLocalState(); + + fakeFolder.syncEngine().setLocalDiscoveryOptions(OCC::LocalDiscoveryStyle::FilesystemOnly); + QVERIFY(fakeFolder.syncOnce()); + + qDebug() << fakeFolder.currentLocalState(); + } }; QTEST_GUILESS_MAIN(TestSyncMove)